Skip to content

Fix CRLF distribution for .bat files; add DLL-specific caveat hint - #435

Merged
mixmansoundude merged 2 commits into
mainfrom
claude/batch-crlf-strategy-pdi9h5
Aug 15, 2026
Merged

Fix CRLF distribution for .bat files; add DLL-specific caveat hint#435
mixmansoundude merged 2 commits into
mainfrom
claude/batch-crlf-strategy-pdi9h5

Conversation

@mixmansoundude

Copy link
Copy Markdown
Owner

Summary

Two independent changes, both closing items from docs/open-questions.md:

1. CRLF distribution fix (former open question 2)

Root cause, confirmed live before this fix: raw.githubusercontent.com/.../run_setup.bat served pure LF (0 CRLF pairs, 5,626 bare LF) even though .gitattributes had *.bat text eol=crlf. Git's text=auto normalizes the stored blob to LF on every commit regardless of any eol= override -- eol= only affects what a real git checkout writes to a working tree, a step raw/blob serving never performs. This is exactly what docs/agent-closed-backlog.md's Item 44 (the runtime line-ending self-check) was mitigating, not fixing.

Fix (combining the open question's own options B + C, per maintainer decision that a real enforcement plan closes option B's stated risk):

  • .gitattributes: *.bat/*.cmd changed to -text (git performs no line-ending conversion at all, in either direction) -- stored blob, working-tree bytes, and raw-served bytes are now always identical.
  • New tools/check_crlf.py (check + --fix) replaces git's own normalization as the enforcement mechanism -- wired into tools/run_sanity_sweep.sh and a new, independent, gating CI job (crlf-check, no needs:, runs immediately). Per this repo's own "gating is a branch-protection setting, not a YAML edit" rule, someone with admin access still needs to add its check name to required-status-checks for it to actually block merges.
  • Renormalized the three tracked .bat files (git add --renormalize) -- a one-time, mechanical full-file diff with no real content change (the working-tree bytes were already genuine CRLF via the old checkout-time conversion; only the stored blob was wrong).
  • Contributor-facing warning banner on all three .bat files: do not edit via the GitHub web editor or a Mac/Linux tool.
  • GitHub Pages (publish_diag job) now also republishes a guaranteed-CRLF run_setup.bat on every push to main -- a second, independent distribution point decoupled entirely from git blob/raw-URL semantics, as a fallback if the raw link ever misbehaves.
  • README: new top-of-file "Just want the file?" pointer, and a revised TL;DR bullet now that raw downloads are expected to work.
  • Optional tools/githooks/pre-commit + CONTRIBUTING.md note (CI is the real gate; this just saves a round-trip).
  • No CI auto-fix-and-commit anywhere -- matches this repo's existing "only inline_model_fix.py may commit auto-fixes" rule.

2. DLL-specific postflight caveat hint (former open question 1, answered yes)

The post-flight caveat panel now surfaces a real, already-computed fact from :dll_bundle_recover (the native-DLL bundling repair loop) instead of staying purely generic. New HP_DLL_HINT_STATE variable (captured before the NDJSON gate, reset once per fresh build attempt) and :pfb_dll_hint subroutine dispatch into 3 wording buckets -- a prior review finding established detection and repair are not the same event, so the wording must not claim more than each state means (skipped / attempted-and-failed / repaired).

Both open questions are now resolved and folded into docs/agent-closed-backlog.md; docs/open-questions.md is back to empty.

Test plan

  • python tools/check_delimiters.py run_setup.bat run_tests.bat tests/dynamic_tests.bat -- clean
  • python tools/check_crlf.py -- all 3 tracked .bat files pure CRLF
  • Verified the staged git blobs are pure CRLF post-renormalize (not just the working tree)
  • python -m compileall -q . / python -m pyflakes . -- clean
  • python -m yamllint .github/workflows/ / actionlint -oneline .github/workflows/*.yml -- clean
  • PowerShell AST parse sweep (tests/*.ps1, tools/*.ps1) -- clean
  • python -m pytest tests/test_*.py -q -- 528 passed, 3 skipped (includes 13 new tests for tools/check_crlf.py)
  • New tests/harness.ps1 static check (batch.dll_bundle.caveat_hint) verified directly against the real run_setup.bat content via a standalone pwsh run of the same regex logic before landing, not just reasoned about
  • ASCII sweep -- clean
  • Diffed LF-normalized old vs. new run_setup.bat to confirm the renormalization commit introduced only the intended banner + DLL-hint changes, nothing else
  • Full Windows CI matrix (real/conda-full gating lanes) -- pending this PR's own CI run

🤖 Generated with Claude Code

https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV


Generated by Claude Code

CRLF strategy (docs/open-questions.md former item 2):
- .gitattributes: *.bat/*.cmd now -text (no git line-ending conversion at
  all) instead of eol=crlf, which only affected checkout, never what
  raw.githubusercontent.com actually served. Confirmed live before this
  fix: the stored blob was 100% LF, 0 CRLF pairs.
- Renormalized run_setup.bat, run_tests.bat, tests/dynamic_tests.bat to
  pure CRLF (git add --renormalize) -- the working-tree bytes were
  already CRLF via the old checkout-time conversion; only the stored
  blob (and therefore the raw URL) was wrong.
- New tools/check_crlf.py (check + --fix) replaces git's own
  normalization as the enforcement mechanism: wired into
  tools/run_sanity_sweep.sh and a new, independent, gating CI job
  (crlf-check in batch-check.yml).
- Contributor-facing warning banner added to all three tracked .bat
  files: do not edit via the GitHub web editor or a Mac/Linux tool.
- GitHub Pages now also publishes a guaranteed-CRLF copy of
  run_setup.bat on every push to main, as an independent fallback
  distribution point decoupled from git blob/raw-URL semantics.
- README: new top-of-file "Just want the file?" pointer plus a revised
  TL;DR bullet now that raw downloads are expected to work correctly.
- Optional tools/githooks/pre-commit + CONTRIBUTING.md note.
- docs/agent-lessons-learned.md: new ".bat files: -text, not eol=crlf"
  entry documents the mechanism and the diff-cleanliness tradeoff.

DLL-specific postflight caveat hint (docs/open-questions.md former item 1,
answered yes): the caveat panel now surfaces a real, already-computed
fact from :dll_bundle_recover instead of staying purely generic, via a
new HP_DLL_HINT_STATE variable and :pfb_dll_hint subroutine dispatching
into 3 wording buckets (skipped / attempted-and-failed / repaired), per
the review finding that detection and repair are not the same event.
Regression guard: tests/harness.ps1's new batch.dll_bundle.caveat_hint.

Both open questions in docs/open-questions.md are now resolved and
folded into docs/agent-closed-backlog.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 246d6115-5080-40a5-bdfb-cb063575aed6

📥 Commits

Reviewing files that changed from the base of the PR and between 6ba02b0 and c35c08b.

📒 Files selected for processing (19)
  • .gitattributes
  • .github/workflows/batch-check.yml
  • .gitignore
  • CLAUDE.md
  • CONTRIBUTING.md
  • README.md
  • docs/agent-closed-backlog.md
  • docs/agent-interconnect.md
  • docs/agent-lessons-learned.md
  • docs/agent-ndjson.md
  • docs/open-questions.md
  • run_setup.bat
  • run_tests.bat
  • tests/dynamic_tests.bat
  • tests/harness.ps1
  • tests/test_check_crlf.py
  • tools/check_crlf.py
  • tools/githooks/pre-commit
  • tools/run_sanity_sweep.sh

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added reliable CRLF preservation and validation for Windows batch files.
    • Added download guidance, including a GitHub Pages mirror for the setup script.
    • Added clearer post-build messages for DLL repair outcomes.
  • Bug Fixes

    • Improved handling and display of unresolved or partially repaired DLL issues.
  • Documentation

    • Updated setup, contribution, and troubleshooting guidance for line endings and downloads.
  • Tests

    • Added automated coverage for CRLF validation, repair, and DLL status messaging.

Walkthrough

The change preserves CRLF bytes for .bat and .cmd files, adds checker and fixer tooling with tests, integrates validation into CI and hooks, documents download handling, and adds DLL post-flight hint regression coverage.

Changes

Batch-file CRLF enforcement

Layer / File(s) Summary
CRLF policy and contributor guidance
.gitattributes, .gitignore, CONTRIBUTING.md, run_tests.bat, tests/dynamic_tests.bat
Batch and command files use -text. Contributor instructions define CRLF-preserving editing and repair.
Checker, fixer, and unit coverage
tools/check_crlf.py, tests/test_check_crlf.py
The utility detects, reports, normalizes, and verifies CRLF endings. Unit and CLI tests cover these behaviors.
CI, sanity sweep, and pre-commit validation
.github/workflows/batch-check.yml, tools/run_sanity_sweep.sh, tools/githooks/pre-commit
CI, the sanity sweep, and the optional hook validate tracked or staged batch files. Pages publishing validates run_setup.bat before copying it.
Distribution and repository documentation
README.md, CLAUDE.md, docs/agent-closed-backlog.md, docs/agent-lessons-learned.md, docs/open-questions.md
Documentation describes byte-preserving downloads, CRLF checks, repair commands, Pages distribution, and resolved line-ending decisions.

DLL post-flight hint coverage

Layer / File(s) Summary
DLL outcome propagation and regression coverage
docs/agent-interconnect.md, tests/harness.ps1, docs/agent-ndjson.md, docs/agent-closed-backlog.md
DLL hint state reset, capture timing, post-flight dispatch, outcome wording, and static registry coverage are documented and checked.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: claude

Sequence Diagram(s)

sequenceDiagram
  participant Git
  participant Checker as tools/check_crlf.py
  participant CI as crlf-check
  participant Pages as GitHub Pages
  Git->>Checker: Discover tracked .bat and .cmd files
  Checker->>CI: Return CRLF validation status
  CI->>Pages: Validate and copy run_setup.bat
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/batch-crlf-strategy-pdi9h5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

CI's ndjson-registry-check (advisory, non-gating) correctly caught this
on PR #435's own run: the new tests/harness.ps1 static check emits
batch.dll_bundle.caveat_hint but it was never added to the doc
registry, violating this repo's own AGENT DIRECTIVE (update the
registry in the same commit as the new row). Verified locally via
tools/check_ndjson_registry.py: 302/302 doc vs code IDs now match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV
@mixmansoundude
mixmansoundude merged commit 769637b into main Aug 15, 2026
17 checks passed
@mixmansoundude
mixmansoundude deleted the claude/batch-crlf-strategy-pdi9h5 branch August 15, 2026 06:24
mixmansoundude added a commit that referenced this pull request Aug 17, 2026
* Fix two stale post-#435 messages; close Item 51; file Item 59

A high-confidence external review (working from the repo alone, no CI
log access) caught two places the CRLF distribution fix (#435) landed
but didn't revisit:

- run_setup.bat's own line-ending self-check panel still told a
  confused user to "re-download using git clone, not the Raw button" --
  true before #435, false and actively bad advice after it (steers a
  git-less Prime Directive user toward a tool they don't have, instead
  of just re-downloading via the now-fixed Raw link). The panel and its
  header comment now describe the check as defense-in-depth against a
  stale/re-saved copy, not a workaround for a still-broken channel.
- :merge_git_config (REQ-015) still wrote *.bat eol=crlf / *.cmd
  eol=crlf into every bootstrapped user's OWN .gitattributes -- the
  exact pattern this repo just proved insufficient for itself. Changed
  to *.bat -text / *.cmd -text, matching this repo's own .gitattributes.

Both fixes updated their matching test assertions
(selfapps_lineending_check.ps1, selfapps_ux_hardening.ps1) and the
REQ-015 spec in README.md in lockstep.

Also closes Active Backlog Item 51 (HP_PIPREQS_RC errorlevel-capture
ordering): the same review settled the underlying cmd.exe semantics
question (a successful plain "set" does not itself touch %errorlevel%,
so this was very likely never a live bug) but the zero-risk reorder fix
was applied anyway, exactly as the item's own note recommended, closing
the cross-call-site inconsistency regardless of who's right.

Files Active Backlog Item 59: CodeRabbit's automated review did not run
on PR #435 (manual-trigger-required repo config) -- standing directive
for future PRs to trigger it via @coderabbitai review, plus a record of
what this pass caught as the motivating evidence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV

* Fix CodeRabbit findings on PR #436

Two real issues caught by CodeRabbit's review:

- selfapps_ux_hardening.ps1's whole-script $allPass aggregate (line
  1184) still referenced $gaBatCrlf, the variable renamed to
  $gaBatText earlier in this same PR. Under PowerShell's non-strict
  mode the undefined reference silently evaluated to $null, making
  $allPass always false regardless of actual test outcomes -- this
  script would have always exited 1. Fixed to reference $gaBatText.

- selfapps_ux_hardening.ps1's non-Windows skip guard used $IsWindows,
  which is undefined under Windows PowerShell 5.1 (only introduced in
  PowerShell 6+). The identical bug was already fixed in the sibling
  selfapps_lineending_check.ps1 (PR #434); this file had not been
  updated to match. Fixed to the same
  [System.Environment]::OSVersion.Platform pattern.

A third finding (:merge_git_config doesn't migrate an existing
.gitattributes with the old eol=crlf rules to -text) is real and
correctly rated "Major, Heavy lift" by CodeRabbit -- left for a
follow-up rather than folded into this PR; it needs a real
read-modify-write against a user's own file plus a new regression
scenario, not a quick fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV

* File Item 60: REQ-015 does not migrate an existing .gitattributes

CodeRabbit's review on PR #436 (rated Major, Heavy lift) correctly
identified that the idempotency guard in :merge_git_config means a
user who already ran an older run_setup.bat keeps *.bat eol=crlf /
*.cmd eol=crlf forever -- item 59's fix only covers a fresh append,
not migrating existing content. Real design questions (replace vs.
append-superseding-rules) mean this needs its own scoping pass rather
than a rushed fix folded into this PR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV

* Fix two more CodeRabbit findings on PR #436

- Test 4's .gitattributes assertion only checked *.bat -text, never
  *.cmd -text, even though :merge_git_config writes both. A regression
  in the .cmd rule specifically could have passed silently. Added
  $gaCmdText, included in both the row's own pass condition and the
  whole-script $allPass aggregate.
- Tagged the -text rationale comment as "# derived requirement:" per
  this repo's own convention for non-obvious constraints.

Verified: PS AST parse clean, check_delimiters.py clean (one
pre-existing, unrelated finding at a shifted line number, confirmed
present before this change too), ASCII clean, markdownlint-cli2
CLAUDE.md clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants